using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace UmlDesigner.Model
{
    [Serializable]
    class SlotManager
    {
        public SlotManager(bool horiz, ItemWidget p)
        {
            horizontal = horiz;
            parent = p;
        }

        public List<Slot> GetAllSlots()
        {
            List<Slot> result = new List<Slot>();
            foreach (Slot s in slots.Values)
            {
                result.Add(s);
            }
            return result;
        }

        public Slot GetSlot(LinkWidget link)
        {
            if (!slots.ContainsKey(link))
            {
                slots.Add(link, new Slot(position, link));
                RecalculateSlotPositions();
            }
            return slots[link];
        }

        public void DeleteSlot(LinkWidget link)
        {
            slots.Remove(link);
            RecalculateSlotPositions();
        }

        public void AddSlot(Slot slot)
        {
            if (!slots.ContainsKey(slot.Link))
            {
                slots.Add(slot.Link, slot);
            }
            RecalculateSlotPositions();
        }

        public void MovePosition(Point centerPos)
        {
            position = centerPos;
            RecalculateSlotPositions();
        }

        private void RecalculateSlotPositions()
        {
            // Each slot has SpacePerSlot pixels.

            int startLoc;
            if (horizontal)
            {
                startLoc = (position.X) - (((slots.Count - 1) * SpacePerSlot) / 2);
            }
            else
            {
                startLoc = (position.Y) - (((slots.Count - 1) * SpacePerSlot) / 2);
            }

            SortedSet<int, Slot> sortedSlots = new SortedSet<int, Slot>();
            foreach (Slot s in slots.Values)
            {
                Point pt;
                if (s.Link.GetSource() == parent)
                {
                    if (s.Link.destSlot != null)
                    {
                        pt = s.Link.destSlot.Position;
                    }
                    else
                    {
                        pt = s.Link.GetDestination().GetClassPosition();
                    }
                }
                else
                {
                    if (s.Link.srcSlot != null)
                    {
                        pt = s.Link.srcSlot.Position;
                    }
                    else
                    {
                        pt = s.Link.GetSource().GetClassPosition();
                    }
                }

                if (horizontal)
                {
                    sortedSlots.Add(pt.X, s);
                }
                else
                {
                    sortedSlots.Add(pt.Y, s);
                }
            }

            foreach (KeyValuePair<int, Slot> s in sortedSlots)
            {
                if (horizontal)
                {
                    s.Value.Position = new Point(startLoc, position.Y);
                }
                else
                {
                    s.Value.Position = new Point(position.X, startLoc);
                }

                startLoc += SpacePerSlot;
            }
        }

        internal void Dump(TreeNode parent)
        {
            TreeNode slotItems = parent.Nodes.Add("Items in slot: " + slots.Count.ToString());
            foreach (KeyValuePair<LinkWidget, Slot> item in slots)
            {
                slotItems.Nodes.Add(item.Key.GetHashCode() + " --> " + item.Value.Position.ToString());
            }
        }

        internal void ShallowCopy(SlotManager target)
        {
            target.parent = parent;
            target.slots = new Dictionary<LinkWidget, Slot>(slots);
            target.horizontal = horizontal;
            target.position = position;
        }

        internal void ClearAllSlots()
        {
            slots.Clear();
        }

        private const int SpacePerSlot = 30;
        private ItemWidget parent;

        private Dictionary<LinkWidget, Slot> slots = new Dictionary<LinkWidget, Slot>();
        private bool horizontal;
        private Point position;

    }
}
